package com.huage.courseplatform.application.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huage.courseplatform.application.mapper.PeriodMapper;
import com.huage.courseplatform.application.mapper.PeriodTemplateItemMapper;
import com.huage.courseplatform.application.mapper.PeriodTemplateMapper;
import com.huage.courseplatform.application.model.entity.Period;
import com.huage.courseplatform.application.model.entity.PeriodTemplate;
import com.huage.courseplatform.application.model.entity.PeriodTemplateItem;
import com.huage.courseplatform.application.model.vo.PeriodTemplateAndItemVO;
import com.huage.courseplatform.application.service.PeriodTemplateItemService;
import com.huage.courseplatform.application.service.PeriodTemplateService;
import com.huage.courseplatform.framework.core.impl.BaseServiceImpl;
import com.huage.courseplatform.framework.utils.BeanCopyUtils;
import com.huage.courseplatform.framework.utils.date.LocalDateTimeUtil;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PeriodTemplateServiceImpl extends BaseServiceImpl<PeriodTemplateMapper, PeriodTemplate> implements PeriodTemplateService {
    @Resource
    PeriodTemplateMapper periodTemplateMapper;

    @Resource
    PeriodTemplateItemMapper  periodTemplateItemMapper;

    @Resource
    PeriodMapper periodMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addPeriodTemplateAndItem(PeriodTemplate periodTemplate, List<PeriodTemplateItem> periodTemplateItemList) {
        periodTemplateMapper.insert(periodTemplate);
        periodTemplateItemList.forEach(periodTemplateItem->{
            periodTemplateItem.setId(periodTemplate.getId());
            periodTemplateItemMapper.insert(periodTemplateItem);
        });

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "Service:PeriodTemplateService:id", key = "#id")
    public void delPeriodTemplateAndItemById(String id) {
        periodTemplateMapper.deleteById(id);
        periodTemplateItemMapper.delete(new QueryWrapper<PeriodTemplateItem>().eq("template_id",id));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delPeriodTemplateAndItemByIds(List<String> ids) {
        ids.forEach(id->{
            periodTemplateMapper.deleteById(id);
            periodTemplateItemMapper.delete(new QueryWrapper<PeriodTemplateItem>().eq("template_id",id));
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "Service:PeriodTemplateService:id", key = "#periodTemplate.id")
    public void updatePeriodTemplateAndItem(PeriodTemplate periodTemplate, List<PeriodTemplateItem> periodTemplateItemList) {
        periodTemplateMapper.updateById(periodTemplate);
        periodTemplateItemMapper.delete(new QueryWrapper<PeriodTemplateItem>().eq("template_id",periodTemplate.getId()));
        periodTemplateItemList.forEach(periodTemplateItem->{
            periodTemplateItemMapper.insert(periodTemplateItem);
        });
    }

    @Override
    @Cacheable(cacheNames = "Service:PeriodTemplateService:id", key = "#id")
    public List<PeriodTemplateAndItemVO> getPeriodTemplateAndItem(String id) {
        return periodTemplateMapper.getPeriodTemplateAndItemById(id);
    }

    @Override
    @CacheEvict(cacheNames = "Service:PeriodTemplateService:id", key = "#periodTemplate.id")
    public boolean saveOrUpdate(PeriodTemplate periodTemplate) {
        return super.saveOrUpdate(periodTemplate);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generatePeriod(String templateId, String businessId,Date startDay, Date endDay) {
        PeriodTemplate periodTemplate = new PeriodTemplate();
        if (StringUtils.isEmpty(templateId)){
            List<PeriodTemplate> periodTemplateList = lambdaQuery().eq(PeriodTemplate::getBusinessId,businessId).eq(PeriodTemplate::getIsTacit,1).list();
            Assert.isTrue(!CollectionUtils.isEmpty(periodTemplateList),"找不到商家默认模板");
            Assert.isTrue(periodTemplateList.size()==1,"商家有多个默认模板");
            periodTemplate = periodTemplateList.get(0);
        }else {
            periodTemplate = lambdaQuery().eq(PeriodTemplate::getBusinessId,businessId).eq(PeriodTemplate::getId,templateId).one();
            Assert.isTrue(!ObjectUtils.isEmpty(periodTemplate),"找不到模板");
        }
        List<PeriodTemplateItem> periodTemplateItemList = periodTemplateItemMapper.selectList(new QueryWrapper<PeriodTemplateItem>().eq("template_id",periodTemplate.getId()));

        Assert.isTrue(!CollectionUtils.isEmpty(periodTemplateItemList),"模板的明细为空");
        /**
         * 过滤出每个星期几
         */
        List<PeriodTemplateItem> mondayPeriodList = periodTemplateItemList
                .stream().filter(periodTemplateItem -> periodTemplateItem.getWeekDay() ==1).collect(Collectors.toList());
        List<PeriodTemplateItem> tuesdayPeriodList = periodTemplateItemList
                .stream().filter(periodTemplateItem -> periodTemplateItem.getWeekDay() ==2).collect(Collectors.toList());
        List<PeriodTemplateItem> wednesdayPeriodList = periodTemplateItemList
                .stream().filter(periodTemplateItem -> periodTemplateItem.getWeekDay() ==3).collect(Collectors.toList());
        List<PeriodTemplateItem> thursdayList = periodTemplateItemList
                .stream().filter(periodTemplateItem -> periodTemplateItem.getWeekDay() ==4).collect(Collectors.toList());
        List<PeriodTemplateItem> fridayPeriodList = periodTemplateItemList
                .stream().filter(periodTemplateItem -> periodTemplateItem.getWeekDay() ==5).collect(Collectors.toList());
        List<PeriodTemplateItem> saturdayPeriodList = periodTemplateItemList
                .stream().filter(periodTemplateItem -> periodTemplateItem.getWeekDay() ==6).collect(Collectors.toList());
        List<PeriodTemplateItem> sundayPeriodList = periodTemplateItemList
                .stream().filter(periodTemplateItem -> periodTemplateItem.getWeekDay() ==7).collect(Collectors.toList());


        LocalDateTime startDayLocalDateTime = LocalDateTimeUtil.parseLdt(startDay);
        LocalDateTime endDayLocalDateTime = LocalDateTimeUtil.parseLdt(endDay);
        LocalDateTime tempLocalDateTime = startDayLocalDateTime;
        /**
         * 遍历时间间隔，添加课时
         */
        while (tempLocalDateTime.isBefore(endDayLocalDateTime) || tempLocalDateTime.isEqual(endDayLocalDateTime)){
            int weekDay = LocalDateTimeUtil.week(tempLocalDateTime);
            if(weekDay == 1 && !CollectionUtils.isEmpty(mondayPeriodList)){
                    //插入所有星期一的课时
                    LocalDateTime finalTempLocalDateTime = tempLocalDateTime;
                    mondayPeriodList.forEach(periodTemplateItem -> {
                        addPeriodByTemplateItem(periodTemplateItem,businessId, finalTempLocalDateTime);
                    });
            }
            if(weekDay == 2 && !CollectionUtils.isEmpty(mondayPeriodList)){
                //插入所有星期二的课时
                LocalDateTime finalTempLocalDateTime = tempLocalDateTime;
                tuesdayPeriodList.forEach(periodTemplateItem -> {
                    addPeriodByTemplateItem(periodTemplateItem,businessId, finalTempLocalDateTime);
                });
            }
            if(weekDay == 3 && !CollectionUtils.isEmpty(mondayPeriodList)){
                //插入所有星期三的课时
                LocalDateTime finalTempLocalDateTime = tempLocalDateTime;
                wednesdayPeriodList.forEach(periodTemplateItem -> {
                    addPeriodByTemplateItem(periodTemplateItem,businessId, finalTempLocalDateTime);
                });
            }
            if(weekDay == 4 && !CollectionUtils.isEmpty(mondayPeriodList)){
                //插入所有星期四的课时
                LocalDateTime finalTempLocalDateTime = tempLocalDateTime;
                thursdayList.forEach(periodTemplateItem -> {
                    addPeriodByTemplateItem(periodTemplateItem,businessId, finalTempLocalDateTime);
                });
            }
            if(weekDay == 5 && !CollectionUtils.isEmpty(mondayPeriodList)){
                //插入所有星期五的课时
                LocalDateTime finalTempLocalDateTime = tempLocalDateTime;
                fridayPeriodList.forEach(periodTemplateItem -> {
                    addPeriodByTemplateItem(periodTemplateItem,businessId, finalTempLocalDateTime);
                });
            }
            if(weekDay == 6 && !CollectionUtils.isEmpty(mondayPeriodList)){
                //插入所有星期六的课时
                LocalDateTime finalTempLocalDateTime = tempLocalDateTime;
                saturdayPeriodList.forEach(periodTemplateItem -> {
                    addPeriodByTemplateItem(periodTemplateItem,businessId, finalTempLocalDateTime);
                });
            }
            if(weekDay == 7 && !CollectionUtils.isEmpty(mondayPeriodList)){
                //插入所有星期天的课时
                LocalDateTime finalTempLocalDateTime = tempLocalDateTime;
                sundayPeriodList.forEach(periodTemplateItem -> {
                    addPeriodByTemplateItem(periodTemplateItem,businessId, finalTempLocalDateTime);
                });
            }
            //日期+1遍历
            tempLocalDateTime = tempLocalDateTime.plusDays(1);
        }


    }

    /**
     * 模板转换课时并插入
     * @param periodTemplateItem
     * @param businessId
     * @param insertDay
     */
    private void addPeriodByTemplateItem(PeriodTemplateItem periodTemplateItem,String businessId,LocalDateTime insertDay){

        LocalTime startTime=  LocalTime.parse(periodTemplateItem.getStartTime(), DateTimeFormatter.ofPattern("HH:mm:ss"));
        LocalTime endTime= LocalTime.parse(periodTemplateItem.getEndTime(), DateTimeFormatter.ofPattern("HH:mm:ss"));


        LocalDateTime startDay = LocalDateTimeUtil.of(insertDay.getYear(), insertDay.getMonthValue(), insertDay.getDayOfMonth(), startTime.getHour(), startTime.getMinute());
        LocalDateTime endDay = LocalDateTimeUtil.of(insertDay.getYear(), insertDay.getMonthValue(), insertDay.getDayOfMonth(), endTime.getHour(), endTime.getMinute());

        String startDayString = LocalDateTimeUtil.parse(startDay);
        String endDayString = LocalDateTimeUtil.parse(endDay);


        Period period = BeanCopyUtils.copyProperties(periodTemplateItem,Period.class);

        period.setBusinessId(businessId);
        period.setStartTime(startDayString);
        period.setEndTime(endDayString);

        periodMapper.insert(period);

    }


}
